#!/usr/bin/env python
# -*- coding: utf-8 -*-

#CRONFILE = '/etc/meliponini/cron'
#NODESFILE = '/etc/meliponini/nodes'

import string,cgi,time,sys,os,json,hashlib,base64
from os import curdir, sep
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
from subprocess import Popen, PIPE

# mysql
import MySQLdb
from MySQLdb import MySQLError
import urllib
from urllib2 import Request, urlopen, URLError, HTTPError
import threading
from datetime import datetime
import socket

import logs, plugin

def log(s):
    logs.log(s)

def doGET(nhost, nport, nuser, npass, uri):
    # construimos la url con autentificación
    url = "http://%s:%s%s" % (nhost, nport, uri)
    req = Request(url, None, {'Authorization': 'Basic ' + base64.b64encode( nuser + ':' + npass )})
    log( "GET %s" % url )
    # Open the url
    fu = urlopen(req, None, 60)
    # Obtain data
    result = fu.read()
    fu.close()
    
    return result


def doPOST(nhost, nport, nuser, npass, uri, data):
    result = None
    
    try:
        # construimos la url con autentificación
        url = "http://%s:%s%s" % (nhost, nport, uri)
        req = Request(url, None, {
            'Authorization': 'Basic ' + base64.b64encode( nuser + ':' + npass ),
            'Content-Type': 'application/x-www-form-urlencoded'
        })
        # Open the url
        fu = urlopen(req, urllib.urlencode(data), 60)
        # Obtain data
        result = fu.read()
        fu.close()
        
    except URLError:
        log( "ERROR: url error: %s" % url )
    
    return result
    

class MeliponiniHTTPHandler(BaseHTTPRequestHandler):
    
    config = None
    
    '''
    def __init__(self, request, client_address, server):
        print "commands length = %d" % len(self.commands)
        if len(self.commands) == 0:
            self.commands.append(['/db/list/', self.commandDbList])
            self.commands.append(['/db/backup/', self.commandDbBackup])
            self.commands.append(['/www/list/', self.commandWwwList])
            self.commands.append(['/www/backup/', self.commandWwwBackup])
            self.commands.append(['/svn/list/', self.commandSvnList])
            self.commands.append(['/svn/backup/', self.commandSvnBackup])
            self.commands.append(['/system/users/', self.commandSystemUsers])
            self.commands.append(['/backup/store/', self.commandBackupStore])
            self.commands.append(['/cron/list/', self.commandCronList])
            self.commands.append(['/cron/exec/', self.commandCronExec])
        
        print request, client_address, server
            
        BaseHTTPRequestHandler.__init__(self, request, client_address, server)
    '''
    
    def do_Plugin(self, method):
        if self.authorize():
            # obtenemos todos los plugins
            for P in plugin.getPlugins(method, self.path):
                for command in P.getHandlers():
                    if self.path.startswith( command['match'] ):
                        command['method']()
                        
                        if P.response == 'json':
                            self.responseJSON(P.data, P.code)
                        elif P.response == 'file':
                            self.responseFile(P.data, P.filename, P.filetype)
                        elif P.response == '401':
                            self.response401()
                        elif P.response == '404':
                            self.response404(self.path)
                        elif P.response == '500':
                            self.response500()
                        return
            
            self.response404(self.path)
        return

    def do_GET(self):
        self.do_Plugin('get')
        
    def do_POST(self):
        self.do_Plugin('post')

        
    def authorize(self):
        # Authorization: Basic YWRtaW46c2VjdW95YXM=
        if 'Authorization' in self.headers and self.headers['Authorization'] == 'Basic ' + base64.b64encode( self.config.USER + ':' + self.config.PASS ):
            return True
        
        # Error, solicitar autentificación
        self.response401()
        return False
        
        
        
    def responseJSON(self, data, code=200):
        # respuesta json
        jsondata = json.dumps(data)
        
        # enviamos datos
        self.send_response(code)
        self.send_header('Content-Type', 'text/plain; charset=utf-8')
        self.end_headers()
        self.wfile.write(jsondata)
        
    def responseFile(self, data, filename, type):
        self.send_response(200)
        self.send_header('Content-Type', type)
        self.send_header('Content-Disposition', 'attachment; filename="'+filename+'"');
        self.end_headers()
        self.wfile.write( data )
        
        
    def response401(self):
        self.send_response(401, 'Authorization Required')
        self.send_header('WWW-Authenticate', 'Basic realm="'+self.config.REALM+'"')
        self.end_headers()
        
    def response404(self, filename):
        self.send_response(404, 'File not found: %s' % filename)
        
    def response500(self):
        self.send_response(500, 'Internal Server Error')
            
            
    '''
    GET /source/{filename}/
    Obtiene un fichero del código fuente de este nodo.
    '''
    def commandSource(self):
        # path = /db/backup/dbname
        filename = self.path.split('/')[2]

        # ruta completa
        dirname = sys.path[0]
        fullpath = dirname + '/' + filename
        
        if os.path.exists(fullpath):
            # cargamos datos del fichero
            filedata = ''
            try:
                f = open(fullpath, 'r')
                filedata = f.read()
                f.close()
            except IOError:
                log( "ERROR: unable to read source file: %s" % filename )
                
            # devolvemos el fichero comprimido
            self.responseFile(filedata, filename, 'text/plain')
            
        else:
            log( "ERROR: path not found: %s" % fullpath )
            self.response404(filename)


    '''
    GET /service/{name}/{start|stop|restart|reload}/
    Maneja los servicios instalados en /etc/init.d/
    '''
    def commandService(self):
        (service, action) = self.path.split('/')[1:3]
        
        path = "/etc/init.d/%s"
        if os.path.exists(path):
            # exec /etc/init.d/{service} {action}
            Popen(['/etc/init.d/'+service, action])
            
            # TODO: devolver true si se ejecutó correctamente
            self.responseJSON("")
        else:
            self.response404(path)

    
    '''
    GET /system/users/
    Nos solicitan información de los usuarios del sistema
    '''
    def commandSystemUsers(self):
        try:
            f = open('/etc/passwd', 'r')
            
            data = []
            
            for line in f:
                line = line.strip(' \n')
                if len(line) > 0:
                    data.append( line.split(':') )
                    
            self.responseJSON(data)
            
        except IOError:
            log( 'cannot read /etc/passwd' )
            self.response500()
            

    


